﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.ServiceModel.Web;
using System.Text;
using System.Xml.Linq;
using MBWebService.Core;
using MBWebService.Core.Classes;
using MBWebService.Core.Enums;
using MBWebService.Core.Interfaces;
using MediaBrowser.Library.Entities;
using MediaBrowser.Library;
using System.Management;
using System.Threading;

namespace MBWebService.Service
{
    public class ServiceHelper : IMediaBrowserService
    {
        #region Private Members

        MediaBrowserServer server;

        private static PlayHelper playHelper;

        private static PlayHelper PlayHelper
        {
            get
            {
                if (playHelper == null)
                    playHelper = new PlayHelper(Plugin.KernelInstance.ConfigData);
                return playHelper;
            }
        }

        private static ServiceHelper instance;
        
        public static ServiceHelper Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new ServiceHelper();
                }

                return instance;
            }
        }

        private MediaBrowserServer Server
        {
            get
            {
                if (this.server == null)
                {
                    this.server = new MediaBrowserServer();
                    this.server.Initialise();
                }
            
                return this.server;
            }
        }

        private static readonly string _imdbMobileTrailersVar = "var trailers = ";
        private static readonly string _localTrailerSource = "LOCAL";

        #endregion
        
        #region IMediaBrowserService Members

        public BasicItem GetItem(Guid id)
        {
            BasicItem retVal = null;
            try
            {
                //Plugin.KernelInstance.EntityResolver
                var bob = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
                if (bob != null)
                {
                    if (bob is Folder)
                    {
                        BasicCollectionItem coll = new BasicCollectionItem(bob);

                        if (coll.Children.Count() == 0)
                        {
                            coll.Children = GetChildren(id);
                        }

                        retVal = coll;
                    }
                    else
                    {
                        retVal = new MetadataItem(bob);
                    }
                }
                else
                {
                    LogMessage("Error finding item '{0}'.", id);
                }
            }
            catch (Exception ex)
            {
                LogMessage("Error getting item '{0}'; ERROR:'{1}'", id, ex.Message);
            }

            return retVal;
        }

        public BasicCollectionItem GetStartUpFolders()
        {
            BasicCollectionItem retVal = null;
            try
            {
                LogMessage("Getting startup");
                AggregateFolder aFolder = Plugin.KernelInstance.RootFolder;
                retVal = new BasicCollectionItem(aFolder);
            }
            catch (Exception ex)
            {
                LogMessage("Error getting startup folders ERROR:'{0}'", ex.Message);
            }

            return retVal;
        }

        public MetadataItem GetMetadata(Guid id)
        {
            MetadataItem retVal = null;
            try
            {
                var bob = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
                retVal = new MetadataItem(bob);
            }
            catch (Exception ex)
            {
                LogMessage("Error getting item '{0}'; ERROR:'{1}'", id, ex.Message);
            }

            return retVal;
        }

        public string getStreamItems(Guid id)
        {
            //Kill ffMpeg if it's running
            foreach (Process clsProcess in Process.GetProcesses())
            {
                if (clsProcess.ProcessName.StartsWith("ffmpeg"))
                {
                    clsProcess.Kill();
                }
            }

            string fnames = @"";
            string tmp = @"";
            //use evergol's code to get each item's video path
            //this is so the user can pick what to stream

            var item = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
            FileAttributes attr = File.GetAttributes(item.Path);
            MediaCollection collection;

            // detect whether its a directory or file
            if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
            {
                collection = GetCollectionFromDirectory(item.Path);
                LogMessage("Attempting to play Direcory '{0}'", item.Path);
            }
            else
            {
                collection = GetCollectionFromFile(item.Path);
                LogMessage("Attempting to play File'{0}'", item.Path);
            }

            if (collection.Count > 0)
            {
                foreach (var collectionItem in collection)
                {
                    if (collectionItem.ToLower().EndsWith("mp3"))
                    {
                    }
                    else
                    {
                        //just pull the filename without path.
                        tmp = collectionItem;
                        if (tmp.LastIndexOf(@"\") > 0)
                        {
                            tmp = tmp.Substring(tmp.LastIndexOf(@"\") + 1);
                            tmp = tmp.Replace(@"\", "");
                        }
                        fnames += tmp + @"||";
                    }
                }
            }
            else
            {
                //Assuming nothing was found, because it has shortcuts? (*.lnk try it manually...
                string[] fileEntries = Directory.GetFiles(item.Path);
                foreach (string fileName in fileEntries)
                {
                    if (fileName.EndsWith(".lnk"))
                    {
                        string realFile = MediaBrowser.Interop.ShortcutNativeMethods.ResolveShortcut(fileName);
                        LogMessage("Attempting to play Fallback File'{0}'", realFile);
                        if (fileName.ToLower().EndsWith("mp3"))
                        {
                        }
                        else
                        {
                            //just pull the filename without path.
                            tmp = fileName.ToString();
                            if (tmp.LastIndexOf(@"\") > 0)
                            {
                                tmp = tmp.Substring(tmp.LastIndexOf(@"\") + 1);
                                tmp = tmp.Replace(@"\", "");
                            }
                            fnames += tmp + @"||";
                        }

                    }
                }

            }


            LogMessage("fnames sent: '{0}'", fnames);

            return fnames;
        }

        public bool StreamItem(Guid id, string fname, string url)
        {
            //Kill ffMpeg if it's running
            foreach (Process clsProcess in Process.GetProcesses())
            {
                if (clsProcess.ProcessName.StartsWith("ffmpeg"))
                {
                    clsProcess.Kill();
                }
            }

            //checking whether things exist
            if (Directory.Exists(AppSettings.MediaBrowserWsDirectory.FullName + @"\web\stream\") == false)
            {
                LogMessage("Streaming Directory not found");
                return false;
            }

            if (File.Exists(AppSettings.MediaBrowserWsDirectory.FullName + @"\web\ffmpeg.exe") == false)
            {
                LogMessage("ffmpeg not found");
                return false;
            }

            //delete files from ffmpeg
            string[] files = Directory.GetFiles(AppSettings.MediaBrowserWsDirectory.FullName + @"\web\stream\");
            foreach (string file in files)
                File.Delete(file);


            string toStream = "";
            //Lookup items in collection and pick the matching query
            var item = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
            FileAttributes attr = File.GetAttributes(item.Path);
            MediaCollection collection;
            if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                collection = GetCollectionFromDirectory(item.Path);
            else
                collection = GetCollectionFromFile(item.Path);

            if (collection.Count > 0)
            {
                foreach (var collectionItem in collection)
                {

                    if (collectionItem.EndsWith(fname))
                    {
                        toStream = collectionItem.ToString();
                    }
                }
            }
            else
            {
                //Assuming nothing was found, because it has shortcuts? (*.lnk try it manually...
                string[] fileEntries = Directory.GetFiles(item.Path);
                foreach (string fileName in fileEntries)
                {
                    if (fileName.EndsWith(".lnk"))
                    {
                        string realFile = MediaBrowser.Interop.ShortcutNativeMethods.ResolveShortcut(fileName);
                        LogMessage("Attempting to play Fallback File'{0}'", realFile);
                        if (fileName.ToLower().EndsWith("mp3"))
                        {
                        }
                        else
                        {
                            toStream = realFile.ToString();
                        }

                    }
                }
            }

            LogMessage("To Stream: '{0}'", toStream);


            if (toStream != "")
            {
                //create args
                string path = AppSettings.MediaBrowserWsDirectory.FullName + @"\web\";
                string WSurl = url + @"web/";
                string FFMPEG = AppSettings.UserSettings.FFMPEGSingleChannel.ToString();
                string fullArg = @"-i """ + toStream + @""" " + FFMPEG + @" | """ + path + @"segmenter.exe"" - 10 stream/stream stream/stream.m3u8 " + WSurl + @" 5 1";

                //Create batch file
                using (StreamWriter writer = new StreamWriter(path + "ffmpeg.bat"))
                {
                    writer.WriteLine(@"CD " + path);
                    writer.WriteLine(path + "ffmpeg.exe " + fullArg);
                }

                //run the batch file
                Process myProcess = new Process();
                ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(path + "ffmpeg.bat");
                myProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                myProcess.StartInfo = myProcessStartInfo;
                myProcess.Start();

                //Process.Start(startInfo);
                myProcess.WaitForExit(10000);

                if (File.Exists(path + @"stream\stream.m3u8"))
                {
                    LogMessage("Stream URL Created");
                    return true;
                }
                else
                {
                    //try again as 2 channel audio
                    FFMPEG = AppSettings.UserSettings.FFMPEGDualChannel.ToString();
                    fullArg = @"-i """ + toStream + @""" " + FFMPEG + @" | """ + path + @"segmenter.exe"" - 10 stream/stream stream/stream.m3u8 " + WSurl + @" 5 1";
                    //reCreate batch file
                    using (StreamWriter writer = new StreamWriter(path + "ffmpeg.bat"))
                    {
                        writer.WriteLine(@"CD " + path);
                        writer.WriteLine(path + "ffmpeg.exe " + fullArg);
                    }
                    //run the batch file
                    myProcess.Start();
                    myProcess.WaitForExit(10000);
                    if (File.Exists(path + @"stream\stream.m3u8"))
                    {
                        LogMessage("Stream URL Created @ 2 channel audio");
                        return true;
                    }
                    else
                    {
                        LogMessage("Stream URL not Created");
                        return false;
                    }

                }
            }
            else
            {
                LogMessage("Nothing to Stream");
                return false;
            }
        }

        public PictureItem GetImage(Guid id, Core.Enums.ImageTypes imageType, int maxHeight, int maxWidth)
        {
            PictureItem retVal = null;
            try
            {
                var item = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
                retVal = new PictureItem(item, imageType, maxWidth, maxHeight);
                WebOperationContext.Current.OutgoingResponse.ContentType = GetContentType(retVal.FileExtension);
            }
            catch (Exception ex)
            {
                LogMessage("Error Retrieving Image for id:'{0}'  :'{1}' ERROR:'{2}'", id, imageType, ex.Message);
            }

            return retVal;
        }

        public BasicCollectionItem GetCollection(Guid id)
        {
            BasicCollectionItem retVal = null;

            try
            {
                BaseItem item = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
                if (item != null)
                {
                    BasicCollectionItem collection = new BasicCollectionItem(item);
                    retVal = collection;
                }
            }
            catch (Exception ex)
            {
                LogMessage("Error getting collection '{0}'; ERROR:'{1}'", id, ex.Message);
            }

            return retVal;
        }

        public TrailerInfo[] GetTrailers(Guid id)
        {
            List<TrailerInfo> trailers = new List<TrailerInfo>();

            if (trailers.Count == 0)
            {
                // nothing was found in the cache, so try from scratch
                var mbItem = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);

                if (mbItem != null)
                {
                    var item = new MetadataItem(mbItem);
                    if (!item.ImdbId.IsNullOrEmpty())
                    {
                        trailers.AddRange(ScrapeImdbMobile(item.ImdbId));
                    }

                    trailers.AddRange(GetLocalTrailers(mbItem));
                }

                CacheTrailers(id, trailers);
            }

            return trailers.ToArray();
        }

        public PlaybackDevice[] GetAttachedDevices()
        {
            return Server.AttachedDevices;
        }

        private const string RECENTLY_ADDED = "Recently added";
        private const string RECENTLY_WATCHED = "Recently watched";

        public BasicCollectionItem GetRecentlyAdded(Guid id)
        {
            BasicCollectionItem retVal = null;

            SortedList<DateTime, BaseItem> list = new SortedList<DateTime, BaseItem>();
            string name = null;
            if (id != Guid.Empty)
            {
                BaseItem item = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
                Folder fold = item as Folder;
                if (fold != null)
                {
                    fold.ValidateChildren();
                    MbMethods.FindRecentUnwatchedChildren(fold, list, Plugin.KernelInstance.ConfigData.RecentItemCount, true);
                    name = string.Format("{0} - {1}", item.Name, RECENTLY_ADDED);
                }
            }
            else
            {
                Folder startup = Plugin.KernelInstance.RootFolder;
                startup.ValidateChildren();
                MbMethods.FindRecentUnwatchedChildren(startup, list, Plugin.KernelInstance.ConfigData.RecentItemCount, false);
                name = RECENTLY_ADDED;
            }

            if (list.Any())
            {
                List<BasicItem> children = new List<BasicItem>();
                foreach (var item in list)
                {
                    BasicItem newItem = new BasicItem(item.Value);
                    newItem.Mode = MediaModes.RecentlyAdded;
                    children.Add(newItem);
                }

                retVal = new BasicCollectionItem(children);
                retVal.Name = name;
                retVal.Mode = MediaModes.RecentlyAdded;
            }

            return retVal;
        }

        public BasicCollectionItem GetRecentlyWatched(Guid id)
        {
            BasicCollectionItem retVal = null;

            SortedList<DateTime, BaseItem> list = new SortedList<DateTime, BaseItem>();
            string name = null;
            if (id != Guid.Empty)
            {
                BaseItem item = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
                Folder fold = item as Folder;
                if (fold != null)
                {
                    fold.ValidateChildren();
                    MbMethods.FindRecentWatchedChildren(fold, list, Plugin.KernelInstance.ConfigData.RecentItemCount, true);
                    name = string.Format("{0} - {1}", item.Name, RECENTLY_WATCHED);
                }
            }
            else
            {
                Folder startup = Plugin.KernelInstance.RootFolder;
                startup.ValidateChildren();
                MbMethods.FindRecentWatchedChildren(startup, list, Plugin.KernelInstance.ConfigData.RecentItemCount, false);
                name = RECENTLY_WATCHED;
            }

            if (list.Any())
            {
                List<BasicItem> children = new List<BasicItem>();
                foreach (var item in list)
                {
                    BasicItem newItem = new BasicItem(item.Value);
                    newItem.Mode = MediaModes.RecentlyWatched;
                    children.Add(newItem);
                }

                retVal = new BasicCollectionItem(children);
                retVal.UnwatchedCount = 0;
                retVal.Name = name;
                retVal.Mode = MediaModes.RecentlyWatched;
            }

            return retVal;
        }

        public bool PlayItem(Guid id, string player, bool queue)
        {
            LogMessage("Attempting to play Id:  '{0}'", id.ToString());
            bool retVal = false;
            try
            {
                var item = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);

                // get the file attributes for file or directory
                FileAttributes attr = File.GetAttributes(item.Path);

                MediaCollection collection;
                // detect whether its a directory or file
                if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                {
                    collection = GetCollectionFromDirectory(item.Path);
                    LogMessage("Attempting to play Direcory '{0}'", item.Path);
                }
                else
                {
                    collection = GetCollectionFromFile(item.Path);
                    LogMessage("Attempting to play File'{0}'", item.Path);
                }

                var device = Server.ResolveDeviceName(player);
                retVal = PlayCollection(device, collection, queue);
                
                if (retVal)
                {
                    Media media = item as Media;
                    if (media != null)
                    {
                        media.PlaybackStatus.PlayCount += 1;
                        media.PlaybackStatus.LastPlayed = DateTime.Now;
                        media.PlaybackStatus.PositionTicks = 0;
                        media.PlaybackStatus.Save();
                    }
                }
            }
            catch (Exception ex)
            {
                LogMessage("Error playing file {0}; ERROR: {1}", id, ex.Message);
            }

            return retVal;
        }

        public bool PlayCollection(PlaybackDevice device, MediaCollection collection, bool queue)
        {
            bool retVal = false;

            int collectionCount = collection.Count;
            if (collectionCount > 0)
            {
                try
                {
                    if (device.IsRemote)
                    {
                        MediaCollection tempCollection = new MediaCollection();
                        foreach (var localItem in collection)
                        {
                            string unc;
                            // Convert urls to UNC paths.
                            if (TryGetLocalFromUncDirectory(localItem, out unc))
                            {
                                tempCollection.Add(unc);
                            }
                            else
                            {
                                string message = string.Format("Unable to convert path {0} to network path. Ensure one of the parent directories is shared", localItem);
                                throw new InvalidOperationException(message);
                            }
                        }

                        // If we get here then there were no issues converting to UNC path..
                        retVal = true;
                    }
                    else if (device.IsMediaCenter)
                    {
                        retVal = PlayHelper.PlayExternalSuccess(collection);
                        if (!retVal)
                        {
                            if (!PlayHelper.IsMcOpen)
                            {
                                if (collectionCount > 1)
                                {
                                    // we need to wait for MediaCenter service to connect to be able to play more than one file.
                                    WaitForMcToStart(device);
                                }
                                else
                                {
                                    // try command line start
                                    StartMediaCenter(string.Format(@"""{0}""", collection.First()));
                                    retVal = true;
                                }
                            }
                        }
                    }

                    if (!retVal)
                    {
                        retVal = Server.PerformAction(device.Name, o => o.PlayItem(collection, queue));
                    }
                }
                catch (Exception ex)
                {
                    LogMessage("Error playing file {0}; ERROR: {1}", collection.First(), ex.Message);
                }
            }

            return retVal;
        }

        public void SendCommand(CommandTypes command, string player)
        {
            Server.PerformAction(player, o => o.SendCommand(command));
        }

        public NowPlayingItem GetNowPlaying(bool waitForUpdate, string player)
        {
            return Server.PerformAction(player, o => o.GetNowPlaying(waitForUpdate));
        }

        public void Seek(int seconds, string player)
        {
            Server.PerformAction(player, o => o.Seek(seconds));
        }

        public void GoToScreen(ScreenType screenType, string extraInfo, string player)
        {
            Server.PerformAction(player, o => o.GoToScreen(screenType, extraInfo));
        }

        public void PlayTrailer(TrailerInfo trailer, string player)
        {
            try
            {
                if (trailer != null)
                {
                    if (trailer.source == _localTrailerSource && !trailer.url.IsNullOrEmpty() && trailer.url.Contains("_"))
                    {
                        // play local trailer
                        string[] urls = trailer.url.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
                        if (urls.Length == 2)
                        {
                            Guid id = new Guid(urls[0]);
                            var item = Plugin.KernelInstance.ItemRepository.RetrieveItem(id);
                            if (item != null && item is Movie)
                            {
                                Movie movie = item as Movie;
                                string trailerPath = movie.TrailerFiles.FirstOrDefault(o => Path.GetFileNameWithoutExtension(o) == urls[1]);
                                if (!trailerPath.IsNullOrEmpty())
                                {
                                    // play streamed trailer
                                    Server.PerformAction(player, o => o.PlayItem(GetCollectionFromFile(trailerPath), false));
                                }
                            }
                        }
                    }
                    else if (!trailer.url.IsNullOrEmpty())
                    {
                        // play streamed trailer
                        Server.PerformAction(player, o => o.PlayItem(GetCollectionFromFile(trailer.url), false));
                    }
                }
            }
            catch (Exception ex)
            {
                MBWebService.Core.Logging.Logger.Instance.LogMessage("Error trying to play trailer: {0},{1}; ERROR: {2}", trailer.source, trailer.url, ex.Message);
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Gets the UNC path for a local path passed to it.  empty string if folder isn't shared
        /// 
        /// </summary>
        /// <param name="local">The local path</param>
        /// <param name="unc">The UNC path</param>
        /// <returns>True if UNC is valid, false otherwise</returns>
        private static bool TryGetLocalFromUncDirectory(string local, out string unc)
        {
            bool retVal = false;
            unc = "";

            try
            {
                if ((local == null) || (local == ""))
                {
                    unc = "";
                    throw new ArgumentNullException("local");
                }

                ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Name FROM Win32_share WHERE path ='" + local.Replace("\\", "\\\\") + "'");
                ManagementObjectCollection coll = searcher.Get();
                if (coll.Count == 1)
                {
                    foreach (ManagementObject share in searcher.Get())
                    {
                        unc = share["Name"] as String;
                        unc = "\\\\" + System.Environment.MachineName + "\\" + unc;
                        retVal = true;
                    }
                }
            }
            catch (Exception) { }

            if (!retVal)
            {
                MBWebService.Core.Logging.Logger.Instance.LogMessage("Unable to convert to network path {0}", local);
            }

            return retVal;
        }

        private IEnumerable<BasicItem> GetChildren(Guid id)
        {
            // temp hack as Children don't seem to be getting populated any more...
            var boob = Plugin.KernelInstance.ItemRepository.RetrieveChildren(id);

            List<BasicItem> children = new List<BasicItem>();
            foreach (var child in boob)
            {
                var item = Plugin.KernelInstance.ItemRepository.RetrieveItem(child.Id);
                if (item != null)
                {
                    children.Add(new BasicItem(item));
                }
            }

            return children;
        }

        private void LogMessage(string message, params object[] stringFormatArgs)
        {
            MBWebService.Core.Logging.Logger.Instance.LogMessage(message, stringFormatArgs);
        }

        private string GetContentType(string type)
        {
            string retVal = string.Empty;

            if (AppSettings.MimeTypes.ContainsKey(type))
            {
                retVal = AppSettings.MimeTypes[type];
            }

            return retVal;
        }

        private IEnumerable<TrailerInfo> ScrapeImdbMobile(string imdbId)
        {
            List<TrailerInfo> trailers = new List<TrailerInfo>();

            string url = string.Format("http://m.imdb.com/title/{0}", imdbId);
            string contents = string.Empty;

            try
            {
                WebResponse objResponse;
                WebRequest objRequest = HttpWebRequest.Create(url);

                objResponse = objRequest.GetResponse();
                if (objResponse != null)
                {
                    using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
                    {
                        contents = sr.ReadToEnd();
                        // Close and clean up the StreamReader
                        sr.Close();
                    }

                    // scrape contents for trailers...
                    int index = contents.IndexOf(_imdbMobileTrailersVar);
                    if (index > 0)
                    {
                        string part = contents.Substring(index + _imdbMobileTrailersVar.Length);
                        int endIndex = part.IndexOf(';');
                        string toParse = part.Substring(0, endIndex);

                        DataContractJsonSerializer serialiser = new DataContractJsonSerializer(typeof(TrailerInfo[]));
                        MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(toParse));
                        object items = serialiser.ReadObject(stream);
                        if (items is TrailerInfo[])
                        {
                            TrailerInfo[] TrailerInfos = items as TrailerInfo[];
                            foreach (var bob in TrailerInfos)
                            {
                                string[] formSplit = bob.format.Split(' ');
                                string format = formSplit[0];
                                string resolution = formSplit[1];
                                // dummy it..
                                TrailerInfo info = new TrailerInfo
                                {
                                    format = format,
                                    resolution = resolution,
                                    url = bob.url,
                                    source = "IMDB-Mobile"
                                };
                                trailers.Add(info);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MBWebService.Core.Logging.Logger.Instance.LogMessage("Error scraping imdb for Id: {0}; ERROR: {1}", imdbId, ex.Message);
            }

            return trailers;
        }

        private IEnumerable<TrailerInfo> GetLocalTrailers(BaseItem mbItem)
        {
            if (mbItem is Movie)
            {
                Movie movie = mbItem as Movie;
                if (movie.ContainsTrailers)
                {
                    foreach (var trailer in movie.TrailerFiles)
                    {
                        yield return new TrailerInfo
                        {
                            source = _localTrailerSource,
                            url = string.Format("{0}_{1}", movie.Id, Path.GetFileNameWithoutExtension(trailer))
                        };
                    }
                }
            }
        }

        private IEnumerable<TrailerInfo> ParseTrailerCacheFile(FileInfo fileInfo)
        {
            List<TrailerInfo> trailers = new List<TrailerInfo>();
            try
            {
                XDocument doc = XDocument.Load(fileInfo.FullName);
                var trailerParts = from bob in doc.Descendants("TrailerInfo")
                                   select new TrailerInfo
                                   {
                                       format = bob.Element("format").Value,
                                       resolution = bob.Element("resolution").Value,
                                       source = bob.Element("source").Value,
                                       url = bob.Element("url").Value,
                                   };
                trailers.AddRange(trailerParts);
            }
            catch (Exception ex)
            {
                MBWebService.Core.Logging.Logger.Instance.LogMessage("Error parsing trailer file {0}; ERROR: {1}", fileInfo.FullName, ex.Message);
            }

            return trailers;
        }

        private void CacheTrailers(Guid id, List<TrailerInfo> trailers)
        {
            XElement trailerElems = new XElement("Trailers",
                                from trailer in trailers
                                select new XElement("TrailerInfo",
                                    new XElement("format", trailer.format),
                                    new XElement("resolution", trailer.resolution),
                                    new XElement("source", trailer.source),
                                    new XElement("url", trailer.url)));

            XDocument doc = new XDocument(trailerElems);
            string filePath = Path.Combine(AppSettings.TrailersCacheDirectory.FullName, string.Format("{0}.xml", id));
            doc.Save(filePath);
        }

        private MediaCollection GetCollectionFromFile(string path)
        {
            MediaCollection collection = new MediaCollection();
            collection.Add(path);

            return collection;
        }

        private MediaCollection GetCollectionFromDirectory(string p)
        {
            MediaCollection collection = new MediaCollection();
            DirectoryInfo dir = new DirectoryInfo(p);
            FileInfo[] files = dir.GetFiles();
            var videos = files.Where(o => MediaBrowser.LibraryManagement.Helper.IsVideo(o.FullName));

            foreach (var vid in videos)
            {
                collection.Add(vid.FullName);
            }

            return collection;
        }

        private void WaitForMcToStart(PlaybackDevice device)
        {
            StartMediaCenter(string.Empty);

            if (!PlayHelper.IsMcOpen)
            {
                DateTime now = DateTime.Now;

                // Wait up to 30 seconds for MediaCenter to start and establish a connection
                while (!Server.AttachedDevices.Any(o => o.Name == device.Name) &&
                    DateTime.Now - now < TimeSpan.FromSeconds(30))
                {
                    Thread.Sleep(TimeSpan.FromSeconds(0.5));
                }
            }
        }

        private static void StartMediaCenter(string commandLineArgs)
        {
            DirectoryInfo systemDir = new DirectoryInfo((Environment.GetFolderPath(Environment.SpecialFolder.System)));
            var windowsDir = systemDir.Parent;
            var ehshellPath = Path.Combine(windowsDir.FullName, @"ehome\ehshell.exe");

            ProcessStartInfo processStartInfo = new ProcessStartInfo(ehshellPath, string.Format(@" {0}", commandLineArgs));
            processStartInfo.RedirectStandardOutput = true;
            processStartInfo.UseShellExecute = false;
            processStartInfo.CreateNoWindow = true;
            processStartInfo.WindowStyle = ProcessWindowStyle.Maximized;

            Process process = new Process();
            process.StartInfo = processStartInfo;
            process.Start();
        }

        #endregion

        
    }
}
